home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / ispell40.lha / ispell-4.0 / priv.c < prev    next >
C/C++ Source or Header  |  1993-05-31  |  7KB  |  423 lines

  1. /* Copyright (C) 1990, 1993 Free Software Foundation, Inc.
  2.  
  3.    This file is part of GNU ISPELL.
  4.  
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 2, or (at your option)
  8.    any later version.
  9.  
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.
  14.  
  15.    You should have received a copy of the GNU General Public License
  16.    along with this program; if not, write to the Free Software
  17.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include <stdio.h>
  20. #include <ctype.h>
  21.  
  22. #ifdef HAVE_MALLOC_H
  23. #include <malloc.h>
  24. #endif
  25.  
  26. #include "ispell.h"
  27. #include "hash.h"
  28.  
  29. static int p_nextsize = 53;    /* first hash size, should be prime */
  30. static char **p_hash, **p_end;
  31. static int p_size, p_used, p_thresh;
  32. static int p_modified;
  33.  
  34. int
  35. p_lookup (word, alllower)
  36.   char *word;
  37.   int alllower;
  38. {
  39.   int code;
  40.   char **pe;
  41.   char local[MAX_WORD_LEN], *p, *q;
  42.  
  43.   if (p_size == 0)
  44.     return (0);
  45.  
  46.   if (alllower)
  47.     {
  48.       p = word;            /* already lower case */
  49.     }
  50.   else
  51.     {
  52.       downcase (local, word);
  53.       p = local;
  54.     }
  55.  
  56.   code = hash (p) % p_size;
  57.   pe = p_hash + code;
  58.   while ((q = *pe))
  59.     {
  60.       if (*q == '!')
  61.     q++;
  62.       if (strcmp (q, p) == 0)
  63.     return (1);
  64.       pe++;
  65.       if (pe == p_end)
  66.     pe = p_hash;
  67.     }
  68.   return (0);
  69. }
  70.  
  71. int
  72. p_delete (word)
  73.   char *word;
  74. {
  75.   int code;
  76.   char **pe;
  77.   char local[MAX_WORD_LEN], *p, *q;
  78.  
  79.   if (p_size == 0)
  80.     return (-1);
  81.  
  82.   downcase (local, word);
  83.   p = local;
  84.  
  85.   code = hash (p) % p_size;
  86.   pe = p_hash + code;
  87.   while ((q = *pe))
  88.     {
  89.       if (*q == '!')
  90.     q++;
  91.       if (strcmp (q, p) == 0)
  92.     {
  93.       (*pe)[0] = '#';
  94.       (*pe)[1] = 0;
  95.       p_modified = 1;
  96.       return (0);
  97.     }
  98.       pe++;
  99.       if (pe == p_end)
  100.     pe = p_hash;
  101.     }
  102.   return (-1);
  103. }
  104.  
  105. int
  106. p_enter (word, copy, keep)
  107.   char *word;
  108.   int copy, keep;
  109. {
  110.   int newsize;
  111.   char **oldp_hash, **pe, *p, *q;
  112.   int oldp_used, oldp_size;
  113.   int code, i;
  114.  
  115.   if (*word == 0)
  116.     return (-1);
  117.  
  118.   if (p_used + 1 >= p_thresh)
  119.     {
  120.       newsize = p_nextsize;
  121.       if (newsize < 0 || newsize < p_size)
  122.     return (-1);
  123.  
  124.       oldp_hash = p_hash;
  125.       oldp_used = p_used;
  126.       oldp_size = p_size;
  127.  
  128.       p_hash = (char **) xcalloc ((unsigned) newsize, sizeof (char *));
  129.       p_used = 0;
  130.       p_size = newsize;
  131.       p_thresh = p_size / 2;
  132.       p_end = p_hash + p_size;
  133.       for (i = 0, pe = oldp_hash; i < oldp_size; i++, pe++)
  134.     {
  135.       if (*pe)
  136.         {
  137.           if (p_enter (*pe, 0, 1) < 0)
  138.         {
  139.           p_hash = oldp_hash;
  140.           p_used = oldp_used;
  141.           p_size = oldp_size;
  142.           p_thresh = p_size / 2;
  143.           p_end = p_hash + p_size;
  144.           return (-1);
  145.         }
  146.         }
  147.     }
  148.       if (oldp_hash)
  149.     free ((char *) oldp_hash);
  150.       p_nextsize = nextprime ((unsigned short) (newsize * 2));
  151.     }
  152.   if (word[0] == '!')
  153.     {
  154.       p = word;
  155.       code = hash (p + 1);
  156.     }
  157.   else if (keep)
  158.     {
  159.       if (copy)
  160.     {
  161.       p = (char *) xmalloc ((unsigned) (strlen (word) + 1));
  162.  
  163.       if (copy == 1)
  164.         downcase (p, word);
  165.       else
  166.         (void) strcpy (p, word);
  167.     }
  168.       else
  169.     {
  170.       p = word;
  171.     }
  172.       code = hash (p);
  173.     }
  174.   else
  175.     {
  176.       p = (char *) xmalloc ((unsigned) (strlen (word) + 2));
  177.       p[0] = '!';
  178.       downcase (p + 1, word);
  179.       code = hash (p + 1);
  180.     }
  181.   /* make sure it is not already there */
  182.   pe = p_hash + (code % p_size);
  183.   while ((q = *pe))
  184.     {
  185.       if (*q == '!')
  186.     {
  187.       if (strcmp (q + 1, p) == 0)
  188.         {
  189.           /* he did 'A', now 'I', skip the '!' */
  190.           (*pe)++;
  191.           return (0);
  192.         }
  193.     }
  194.       else if (strcmp (q, p) == 0)
  195.     {
  196.       return (0);
  197.     }
  198.       pe++;
  199.       if (pe == p_end)
  200.     pe = p_hash;
  201.     }
  202.   *pe = p;
  203.   p_used++;
  204.   if (keep)
  205.     p_modified = 1;
  206.   addchars (p);
  207.   return (0);
  208. }
  209.  
  210.  
  211. int
  212. p_load (file, keep)
  213.   char *file;
  214.   int keep;
  215. {
  216.   FILE *f;
  217.   int nwords;
  218.   int c;
  219.   char buf[MAX_WORD_LEN], *p, *start;
  220.  
  221.   int omodified;
  222.  
  223.   omodified = p_modified;
  224.  
  225.   if ((f = fopen (file, "r")) == NULL)
  226.     return (-1);
  227.  
  228.   nwords = 0;
  229.  
  230.   while ((c = getc (f)) != EOF)
  231.     if (c == '\n')
  232.       nwords++;
  233.  
  234.  
  235.   p_nextsize += nextprime ((unsigned) ((nwords + 20) * 2));
  236.  
  237.   rewind (f);
  238.   while (fgets (buf, sizeof buf, f) != NULL)
  239.     {
  240.       if (buf[0] == '#')
  241.     continue;
  242.       downcase (buf, buf);
  243.       start = buf;
  244.       while (isspace (*start))
  245.     start++;
  246.       for (p = start; *p && !isspace (*p); p++)
  247.     ;
  248.       *p = 0;
  249.       if (*start == 0)
  250.     continue;
  251.       addchars (start);
  252.       if (p_enter (start, 1, keep) < 0)
  253.     {
  254.       (void) fclose (f);
  255.       return (-1);
  256.     }
  257.     }
  258.   (void) fclose (f);
  259.   p_modified = omodified;
  260.   return (0);
  261. }
  262.  
  263.  
  264. void
  265. addchars (word)
  266.   char *word;
  267. {
  268.   char *p;
  269.   int c;
  270.  
  271.   for (p = word; *p; p++)
  272.     {
  273.       /* characters above 128 and certain ascii
  274.          * characters can be promoted to be LEXLETTERS
  275.          * if they appear in the ispell.words file
  276.          */
  277.       c = *(unsigned char *) p;
  278.       if (c >= 128 || strchr ("$*+-/_~", c) != NULL)
  279.     {
  280.       (ctbl + 1)[c] |= LEXLETTER;
  281.       if (near_map[c] == 0)
  282.         {
  283.           near_map[c] = 1;
  284.           near_miss_letters[nnear_miss_letters++]
  285.         = c;
  286.         }
  287.     }
  288.     }
  289. }
  290.  
  291.  
  292. int
  293. p_dump (file)
  294.   char *file;
  295. {
  296.   FILE *f;
  297.   char **pe;
  298.   char *bakname;
  299.  
  300.   if (p_size == 0 || p_modified == 0)
  301.     return (0);
  302.  
  303.   bakname = (char *) xmalloc ((unsigned) (strlen (file) + 50));
  304.  
  305.   (void) strcpy (bakname, file);
  306.   (void) strcat (bakname, ".bak");
  307.   (void) unlink (bakname);
  308.   if (link (file, bakname) >= 0)
  309.     (void) unlink (file);
  310.  
  311.   if ((f = fopen (file, "w")) == NULL)
  312.     {
  313.       free (bakname);
  314.       return (-1);
  315.     }
  316.  
  317.   pe = p_hash;
  318.  
  319.   while (pe != p_end)
  320.     {
  321.       if (*pe && **pe != '!' && **pe != '#')
  322.     {
  323.       fputs (*pe, f);
  324.       putc ('\n', f);
  325.     }
  326.       pe++;
  327.     }
  328.  
  329.   if (ferror (f))
  330.     {
  331.       (void) fclose (f);
  332.       (void) unlink (file);
  333.       (void) link (bakname, file);
  334.       (void) unlink (bakname);
  335.       free (bakname);
  336.       return (-1);
  337.     }
  338.  
  339.   (void) fclose (f);
  340.   p_modified = 0;
  341.   (void) unlink (bakname);
  342.   free (bakname);
  343.   return (0);
  344. }
  345.  
  346.  
  347. int
  348. p_reload ()
  349. {
  350.   char **pe;
  351.   extern char *privname;
  352.  
  353.   if (privname == (char *) NULL)
  354.     return (-1);
  355.  
  356.   if (p_size)
  357.     {
  358.       pe = p_hash;
  359.       while (pe != p_end)
  360.     {
  361.       if (*pe)
  362.         free (*pe);
  363.       pe++;
  364.     }
  365.       free ((char *) p_hash);
  366.     }
  367.   p_nextsize = 53;
  368.   p_hash = (char **) NULL;
  369.   p_end = (char **) NULL;
  370.   p_size = 0;
  371.   p_used = 0;
  372.   p_thresh = 0;
  373.   p_modified = 0;
  374.   return (p_load (privname, 1));
  375. }
  376.  
  377. #if 0
  378. main ()
  379. {
  380.   char buf[100];
  381.   char *p;
  382.   if (p_load ("testpriv", 1) < 0)
  383.     (void) printf ("couldn't load testpriv\n");
  384.  
  385.   while (gets (buf) != NULL)
  386.     {
  387.       switch (buf[0])
  388.     {
  389.     case 'l':
  390.       p = buf + 2;
  391.       if (p_lookup (p, 0))
  392.         (void) printf ("%s: ok\n", p);
  393.       else
  394.         (void) printf ("%s: not found\n", p);
  395.       break;
  396.     case 'i':
  397.     case 'a':
  398.       p = buf + 2;
  399.       while (*p)
  400.         {
  401.           if (isupper (*p))
  402.         *p = _tolower (*p);
  403.           p++;
  404.         }
  405.       p = buf + 2;
  406.       if (p_enter (p, 1, buf[0] == 'i' ? 1 : 0) < 0)
  407.         (void) printf ("enter failed\n");
  408.       else
  409.         (void) printf ("ok\n");
  410.       break;
  411.     default:
  412.       (void) printf ("unknown cmd %s\n", buf);
  413.       break;
  414.     }
  415.     }
  416.  
  417.   if (p_dump ("testpriv") < 0)
  418.     (void) printf ("dump failed\n");
  419.  
  420. }
  421.  
  422. #endif
  423.